home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / hplip / base / imagesize.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  5.8 KB  |  218 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2001-2008 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20.  
  21. #
  22. # Ported from Perl's Image::Size module by Randy J. Ray
  23. #
  24.  
  25. # Std Lib
  26. import os
  27. import os.path
  28. import re
  29. import struct
  30.  
  31. # Re patterns
  32. xbm_pat = re.compile(r'^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)', re.IGNORECASE)
  33. xpm_pat = re.compile(r'"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*"', re.IGNORECASE)
  34. ppm_pat1 = re.compile(r'^\#.*', re.IGNORECASE | re.MULTILINE)
  35. ppm_pat2 = re.compile(r'^(P[1-6])\s+(\d+)\s+(\d+)', re.IGNORECASE)
  36. ppm_pat3 = re.compile(r'IMGINFO:(\d+)x(\d+)', re.IGNORECASE)
  37. tiff_endian_pat = re.compile(r'II\x2a\x00')
  38.  
  39.  
  40. def readin(stream, length, offset=0):
  41.     if offset != 0:
  42.         stream.seek(offset, 0)
  43.  
  44.     return stream.read(length)
  45.  
  46.  
  47. def xbmsize(stream):
  48.     width, height = -1, -1
  49.     match = xbm_pat.match(readin(stream,1024))
  50.  
  51.     try:
  52.         width = int(match.group(1))
  53.         height = int(match.group(2))
  54.     except:
  55.         pass
  56.  
  57.     return width, height
  58.  
  59.  
  60. def xpmsize(stream):
  61.     width, height = -1, -1
  62.     match = re.search(xpm_pat, readin(stream, 1024))
  63.     try:
  64.         width = int(match.group(1))
  65.         height = int(match.group(2))
  66.     except:
  67.         pass
  68.  
  69.     return width, height
  70.  
  71.  
  72. def pngsize(stream): # also does MNG
  73.     width, height = -1, -1
  74.  
  75.     if readin(stream, 4, 12) in ('IHDR', 'MHDR'):
  76.         height, width = struct.unpack("!II", stream.read(8))
  77.  
  78.     return width,height
  79.  
  80.  
  81. def jpegsize(stream):
  82.     width, height = -1, -1
  83.     stream.seek(2)
  84.     while True:
  85.         length = 4
  86.         buffer = readin(stream, length)
  87.         try:
  88.             marker, code, length = struct.unpack("!c c h", buffer)
  89.         except:
  90.             break
  91.  
  92.         if marker != '\xff':
  93.             break
  94.  
  95.         if 0xc0 <= ord(code) <= 0xc3:
  96.             length = 5
  97.             height, width = struct.unpack("!xhh", readin(stream, length))
  98.  
  99.         else:
  100.             readin(stream, length-2)
  101.  
  102.     return width, height
  103.  
  104.  
  105. def ppmsize(stream):
  106.     width, height = -1, -1
  107.     header = re.sub(ppm_pat1, '', readin(stream, 1024))
  108.     match = ppm_pat2.match(header)
  109.     typ = ''
  110.     try:
  111.         typ = match.group(1)
  112.         width = int(match.group(2))
  113.         height = int(match.group(3))
  114.     except:
  115.         pass
  116.  
  117.     if typ == 'P7':
  118.         match = ppm_pat3.match(header)
  119.  
  120.         try:
  121.             width = int(match.group(1))
  122.             height = int(match.group(2))
  123.         except:
  124.             pass
  125.  
  126.     return width, height
  127.  
  128.  
  129. def tiffsize(stream):
  130.     header = readin(stream, 4)
  131.     endian = ">"
  132.     match = tiff_endian_pat.match(header)
  133.  
  134.     if match is not None:
  135.         endian = "<"
  136.  
  137.     input = readin(stream, 4, 4)
  138.     offset = struct.unpack('%si' % endian, input)[0]
  139.     num_dirent = struct.unpack('%sH' % endian, readin(stream, 2, offset))[0]
  140.     offset += 2
  141.     num_dirent = offset+(num_dirent*12)
  142.     width, height = -1, -1
  143.  
  144.     while True:
  145.         ifd = readin(stream, 12, offset)
  146.  
  147.         if ifd == '' or offset > num_dirent:
  148.             break
  149.  
  150.         offset += 12
  151.         tag = struct.unpack('%sH'% endian, ifd[0:2])[0]
  152.         type = struct.unpack('%sH' % endian, ifd[2:4])[0]
  153.  
  154.         if tag == 0x0100:
  155.             width = struct.unpack("%si" % endian, ifd[8:12])[0] 
  156.  
  157.         elif tag == 0x0101:
  158.             height = struct.unpack("%si" % endian, ifd[8:12])[0] 
  159.  
  160.     return width, height
  161.  
  162.  
  163. def bmpsize(stream):
  164.     width, height = struct.unpack("<II", readin(stream, 8, 18))
  165.     return width, height
  166.  
  167.  
  168. def gifsize(stream):
  169.     # since we only care about the printed size of the image
  170.     # we only need to get the logical screen sizes, which are
  171.     # the maximum extents of the image. This code is much simpler
  172.     # than the code from Image::Size
  173.     #width, height = -1, -1
  174.     buf = readin(stream, 7, 6) # LSx, GCTF, etc 
  175.     height, width, flags, bci, par = struct.unpack('<HHBBB', buf)
  176.  
  177.     return width, height
  178.  
  179.  
  180.  
  181.  
  182. TYPE_MAP = {re.compile('^GIF8[7,9]a')              : ('image/gif', gifsize),
  183.              re.compile("^\xFF\xD8")                : ('image/jpeg', jpegsize),
  184.              re.compile("^\x89PNG\x0d\x0a\x1a\x0a") : ('image/png', pngsize),
  185.              re.compile("^P[1-7]")                  : ('image/x-portable-pixmap', ppmsize),
  186.              re.compile('\#define\s+\S+\s+\d+')     : ('image/x-xbitmap', xbmsize),
  187.              re.compile('\/\* XPM \*\/')            : ('image/x-xpixmap', xpmsize),
  188.              re.compile('^MM\x00\x2a')              : ('image/tiff', tiffsize),
  189.              re.compile('^II\*\x00')                : ('image/tiff', tiffsize),
  190.              re.compile('^BM')                      : ('image/x-bitmap', bmpsize),
  191.              re.compile("^\x8aMNG\x0d\x0a\x1a\x0a") : ('image/png', pngsize),
  192.            }
  193.  
  194.  
  195. def imagesize(filename, mime_type=''):
  196.     width, height = -1, -1
  197.  
  198.     f = file(filename, 'r')
  199.     buffer = f.read(4096)
  200.  
  201.     if not mime_type:
  202.         for t in TYPE_MAP:
  203.             match = t.search(buffer)
  204.             if match is not None:
  205.                 mime_type, func = TYPE_MAP[t]
  206.                 break
  207.  
  208.     if mime_type and func:
  209.         f.seek(0)
  210.         width, height = func(f)
  211.     else:
  212.         width, height = -1, -1
  213.  
  214.     f.close()
  215.  
  216.     return height, width, mime_type
  217.  
  218.